<!DOCTYPE html>
<html class="writer-html5" lang="en" data-content_root="../">
<head>
  <meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Term and goal expansion &mdash; The Logtalk Handbook v3.93.0-b01 documentation</title>
      <link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=d75fae25" />
      <link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=19f00094" />
      <link rel="stylesheet" type="text/css" href="../_static/css/custom.css?v=396eccfe" />

  
  <!--[if lt IE 9]>
    <script src="../_static/js/html5shiv.min.js"></script>
  <![endif]-->
  
        <script src="../_static/jquery.js?v=5d32c60e"></script>
        <script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
        <script src="../_static/documentation_options.js?v=c8100655"></script>
        <script src="../_static/doctools.js?v=9a2dae69"></script>
        <script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
    <script src="../_static/js/theme.js"></script>
    <!-- begin favicon -->
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
    <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
    <link rel="manifest" href="/site.webmanifest" />
    <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5" />
    <meta name="msapplication-TileColor" content="#355b95" />
    <meta name="theme-color" content="#ffffff" />
    <!-- end favicon -->
    
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" />
    <link rel="next" title="Documenting" href="documenting.html" />
    <link rel="prev" title="Printing messages and asking questions" href="printing.html" />
   
</head>

<body class="wy-body-for-nav"> 
  <div class="wy-grid-for-nav">
    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search" >

          
          
          <a href="../index.html" class="icon icon-home">
            The Logtalk Handbook
              <img src="../_static/logtalk.gif" class="logo" alt="Logo"/>
          </a>
              <div class="version">
                3.93.0
              </div>
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>
        </div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
    
              <p class="caption" role="heading"><span class="caption-text">Contents</span></p>
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal" href="index.html">User Manual</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="declarative.html">Declarative object-oriented programming</a></li>
<li class="toctree-l2"><a class="reference internal" href="features.html">Main features</a></li>
<li class="toctree-l2"><a class="reference internal" href="nomenclature.html">Nomenclature</a></li>
<li class="toctree-l2"><a class="reference internal" href="messages.html">Messages</a></li>
<li class="toctree-l2"><a class="reference internal" href="objects.html">Objects</a></li>
<li class="toctree-l2"><a class="reference internal" href="protocols.html">Protocols</a></li>
<li class="toctree-l2"><a class="reference internal" href="categories.html">Categories</a></li>
<li class="toctree-l2"><a class="reference internal" href="predicates.html">Predicates</a></li>
<li class="toctree-l2"><a class="reference internal" href="inheritance.html">Inheritance</a></li>
<li class="toctree-l2"><a class="reference internal" href="events.html">Event-driven programming</a></li>
<li class="toctree-l2"><a class="reference internal" href="threads.html">Multi-threading programming</a></li>
<li class="toctree-l2"><a class="reference internal" href="errors.html">Error handling</a></li>
<li class="toctree-l2"><a class="reference internal" href="reflection.html">Reflection</a></li>
<li class="toctree-l2"><a class="reference internal" href="programming.html">Writing and running applications</a></li>
<li class="toctree-l2"><a class="reference internal" href="printing.html">Printing messages and asking questions</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Term and goal expansion</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#defining-expansions">Defining expansions</a></li>
<li class="toctree-l3"><a class="reference internal" href="#expanding-grammar-rules">Expanding grammar rules</a></li>
<li class="toctree-l3"><a class="reference internal" href="#bypassing-expansions">Bypassing expansions</a></li>
<li class="toctree-l3"><a class="reference internal" href="#hook-objects">Hook objects</a></li>
<li class="toctree-l3"><a class="reference internal" href="#virtual-source-file-terms-and-loading-context">Virtual source file terms and loading context</a></li>
<li class="toctree-l3"><a class="reference internal" href="#default-compiler-expansion-workflow">Default compiler expansion workflow</a></li>
<li class="toctree-l3"><a class="reference internal" href="#user-defined-expansion-workflows">User defined expansion workflows</a></li>
<li class="toctree-l3"><a class="reference internal" href="#using-prolog-defined-expansions">Using Prolog defined expansions</a></li>
<li class="toctree-l3"><a class="reference internal" href="#debugging-expansions">Debugging expansions</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="documenting.html">Documenting</a></li>
<li class="toctree-l2"><a class="reference internal" href="debugging.html">Debugging</a></li>
<li class="toctree-l2"><a class="reference internal" href="performance.html">Performance</a></li>
<li class="toctree-l2"><a class="reference internal" href="installing.html">Installing Logtalk</a></li>
<li class="toctree-l2"><a class="reference internal" href="migration.html">Prolog integration and migration</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../refman/index.html">Reference Manual</a></li>
<li class="toctree-l1"><a class="reference internal" href="../tutorial/index.html">Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="../faq/index.html">FAQ</a></li>
<li class="toctree-l1"><a class="reference internal" href="../devtools/index.html">Developer Tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../libraries/index.html">Libraries</a></li>
<li class="toctree-l1"><a class="reference internal" href="../ports/index.html">Ports</a></li>
<li class="toctree-l1"><a class="reference internal" href="../contributions/index.html">Contributions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../glossary.html">Glossary</a></li>
<li class="toctree-l1"><a class="reference internal" href="../bibliography.html">Bibliography</a></li>
<li class="toctree-l1"><a class="reference internal" href="../genindex.html">Index</a></li>
</ul>

    <p class="caption"><span class="caption-text">External Contents</span></p>
    <ul>
    <li class="toctree-l1"><a class="reference internal" href="../../apis/index.html">APIs</a></li>
    <li class="toctree-l1"><a class="reference internal" href="https://logtalk.org">Logtalk website</a></li>
    <li class="toctree-l1"><a class="reference internal" href="https://github.com/LogtalkDotOrg/logtalk3">GitHub repo</a></li>
    </ul>
  
        </div>
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
          <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
          <a href="../index.html">The Logtalk Handbook</a>
      </nav>

      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="Page navigation">
  <ul class="wy-breadcrumbs">
      <li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li>
          <li class="breadcrumb-item"><a href="index.html">User Manual</a></li>
      <li class="breadcrumb-item active">Term and goal expansion</li>
      <li class="wy-breadcrumbs-aside">
              <a href="https://github.com/LogtalkDotOrg/logtalk3/blob/master/docs/handbook/sources/userman/expansion.rst" class="fa fa-github"> Edit on GitHub</a>
      </li>
  </ul>
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
             
  <section id="term-and-goal-expansion">
<span id="expansion-expansion"></span><h1>Term and goal expansion<a class="headerlink" href="#term-and-goal-expansion" title="Link to this heading"></a></h1>
<p>Logtalk supports a <em>term and goal expansion mechanism</em> that can be used to
define source-to-source transformations. Two common uses are the definition
of language extensions and domain-specific languages.</p>
<p>Logtalk improves upon the term-expansion mechanism found on some Prolog
systems by providing the user with fine-grained control on <em>if</em>, <em>when</em>,
and <em>how</em> expansions are applied. It allows declaring in a source file itself
which expansions, if any, will be used when compiling it. It allows declaring
which expansions will be used when compiling a file using compile and loading
predicate options. It also allows defining a default expansion for all source
files. It defines a concept of <em>hook objects</em> that can be used as building
blocks to create custom and reusable <em>expansion workflows</em> with explicit and
well-defined semantics. It prevents the simple act of loading expansion rules
affecting subsequent compilation of files. It prevents conflicts between groups
of expansion rules of different origins. It avoids a set of buggy expansion
rules from breaking other sets of expansion rules.</p>
<section id="defining-expansions">
<h2>Defining expansions<a class="headerlink" href="#defining-expansions" title="Link to this heading"></a></h2>
<p>Term and goal expansions are defined using, respectively, the predicates
<a class="reference internal" href="../refman/methods/term_expansion_2.html#methods-term-expansion-2"><span class="std std-ref">term_expansion/2</span></a> and <a class="reference internal" href="../refman/methods/goal_expansion_2.html#methods-goal-expansion-2"><span class="std std-ref">goal_expansion/2</span></a>, which
are declared in the <a class="reference external" href="../../apis/expanding_0.html#expanding-0" title="(in Logtalk APIs v3.93.0)"><span class="xref std std-ref">expanding</span></a> built-in protocol.
Note that, unlike Prolog systems also providing these two predicates, they
are <strong>not</strong> declared as <a class="reference internal" href="../glossary.html#term-multifile-predicate"><span class="xref std std-term">multifile predicates</span></a>
in the protocol. This design decision is key for giving the programmer full
control of the expansion process and preventing the problems inflicting most
of the Prolog systems that provide a term-expansion mechanism.</p>
<p>An example of an object defining expansion rules:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">object</span>(an_object,
    <span class="k">implements</span>(expanding)).

    <span class="k">term_expansion</span>(ping, pong).
    <span class="k">term_expansion</span>(
        colors,
        [white, yellow, blue, green, read, black]
    ).

    <span class="k">goal_expansion</span>(a, b).
    <span class="k">goal_expansion</span>(b, c).
    <span class="k">goal_expansion</span>(<span class="nv">X</span> <span class="k">is</span> <span class="nv">Expression</span>, <span class="k">true</span>) <span class="o">:-</span>
        <span class="k">catch</span>(<span class="nv">X</span> <span class="k">is</span> <span class="nv">Expression</span>, <span class="nv">_</span>, <span class="k">fail</span>).

<span class="p">:- </span><span class="k">end_object</span>.
</pre></div>
</div>
<p>These predicates can be explicitly called using the <a class="reference internal" href="../refman/methods/expand_term_2.html#methods-expand-term-2"><span class="std std-ref">expand_term/2</span></a>
and <a class="reference internal" href="../refman/methods/expand_goal_2.html#methods-expand-goal-2"><span class="std std-ref">expand_goal/2</span></a> built-in methods or called automatically
by the compiler when compiling a source file (see the section below on <em>hook
objects</em>).</p>
<p>In the case of source files referenced in <a class="reference internal" href="../refman/directives/include_1.html#directives-include-1"><span class="std std-ref">include/1</span></a>
directives, expansions are only applied automatically when the directives are
found in source files, not when used as arguments in the <a class="reference internal" href="../refman/predicates/create_object_4.html#predicates-create-object-4"><span class="std std-ref">create_object/4</span></a>,
<a class="reference internal" href="../refman/predicates/create_protocol_3.html#predicates-create-protocol-3"><span class="std std-ref">create_protocol/3</span></a>, and <a class="reference internal" href="../refman/predicates/create_category_4.html#predicates-create-category-4"><span class="std std-ref">create_category/4</span></a>,
predicates. This restriction prevents inconsistent results when, for example,
an expansion is defined for a predicate with clauses found in both an included
file and as argument in a call to the <code class="docutils literal notranslate"><span class="pre">create_object/4</span></code> predicate.</p>
<p>Clauses for the <code class="docutils literal notranslate"><span class="pre">term_expansion/2</span></code> predicate are called until one of them
succeeds. The returned expansion can be a single term or a list of terms
(including the empty list). For example:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- an_object::expand_term(ping, Term).

Term = pong
yes

| ?- an_object::expand_term(colors, Colors).

Colors = [white, yellow, blue, green, read, black]
yes
</pre></div>
</div>
<p>When no <code class="docutils literal notranslate"><span class="pre">term_expansion/2</span></code> clause applies, the same term that we are
trying to expand is returned:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- an_object::expand_term(sounds, Sounds).

Sounds = sounds
yes
</pre></div>
</div>
<p>Clauses for the <code class="docutils literal notranslate"><span class="pre">goal_expansion/2</span></code> predicate are recursively called on the
expanded goal until a fixed point is reached. For example:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- an_object::expand_goal(a, Goal).

Goal = c
yes

| ?- an_object::expand_goal(X is 3+2*5, Goal).

X = 13,
Goal = true
yes
</pre></div>
</div>
<p>When no <code class="docutils literal notranslate"><span class="pre">goal_expansion/2</span></code> clause applies, the same goal that we are
trying to expand is returned:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- an_object::expand_goal(3 =:= 5, Goal).

Goal = (3=:=5)
yes
</pre></div>
</div>
<p>The goal-expansion mechanism prevents an infinite loop when expanding a goal
by checking that a goal to be expanded was not the result from a previous
expansion of the same goal. For example, consider the following object:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">object</span>(fixed_point,
    <span class="k">implements</span>(expanding)).

    <span class="k">goal_expansion</span>(a, b).
    <span class="k">goal_expansion</span>(b, c).
    <span class="k">goal_expansion</span>(c, (a <span class="o">-&gt;</span> b<span class="o">;</span> c)).

<span class="p">:- </span><span class="k">end_object</span>.
</pre></div>
</div>
<p>The expansion of the goal <code class="docutils literal notranslate"><span class="pre">a</span></code> results in the goal <code class="docutils literal notranslate"><span class="pre">(a</span> <span class="pre">-&gt;</span> <span class="pre">b;</span> <span class="pre">c)</span></code> with no
attempt to further expand the <code class="docutils literal notranslate"><span class="pre">a</span></code>, <code class="docutils literal notranslate"><span class="pre">b</span></code>, and <code class="docutils literal notranslate"><span class="pre">c</span></code> goals as they have
already been expanded.</p>
<p>Goal-expansion applies to goal arguments of control constructs, meta-arguments
in built-in or <code class="docutils literal notranslate"><span class="pre">user</span></code> defined meta-predicates, meta-arguments in local
user-defined meta-predicates, meta-arguments in meta-predicate messages when
static binding is possible, and <code class="docutils literal notranslate"><span class="pre">initialization/1</span></code>, <code class="docutils literal notranslate"><span class="pre">if/1</span></code>, and <code class="docutils literal notranslate"><span class="pre">elif/1</span></code>
directives.</p>
</section>
<section id="expanding-grammar-rules">
<h2>Expanding grammar rules<a class="headerlink" href="#expanding-grammar-rules" title="Link to this heading"></a></h2>
<p>A common term expansion is the translation of grammar rules into predicate
clauses. This transformation is performed automatically by the compiler
when a source file entity defines grammar rules. It can also be done
explicitly by calling the <code class="docutils literal notranslate"><span class="pre">expand_term/2</span></code> built-in method. For example:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- logtalk::expand_term((a --&gt; b, c), Clause).

Clause = (a(A,B) :- b(A,C), c(C,B))
yes
</pre></div>
</div>
<p>Note that the default translation of grammar rules can be overridden by
defining clauses for the <a class="reference internal" href="../refman/methods/term_expansion_2.html#methods-term-expansion-2"><span class="std std-ref">term_expansion/2</span></a> predicate.</p>
</section>
<section id="bypassing-expansions">
<h2>Bypassing expansions<a class="headerlink" href="#bypassing-expansions" title="Link to this heading"></a></h2>
<p>Terms and goals wrapped by the <a class="reference internal" href="../refman/control/external_call_1.html#control-external-call-1"><span class="std std-ref">{}/1</span></a> control
construct are not expanded. For example:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- an_object::expand_term({ping}, Term).

Term = {ping}
yes

| ?- an_object::expand_goal({a}, Goal).

Goal = {a}
yes
</pre></div>
</div>
<p>This also applies to source file terms and source file goals when using hook
objects (discussed next).</p>
</section>
<section id="hook-objects">
<h2>Hook objects<a class="headerlink" href="#hook-objects" title="Link to this heading"></a></h2>
<p>Term and goal expansion of a source file during its compilation is performed
by using <em>hook objects</em>. A hook object is simply an object implementing the
<a class="reference external" href="../../apis/expanding_0.html#expanding-0" title="(in Logtalk APIs v3.93.0)"><span class="xref std std-ref">expanding</span></a> built-in protocol and defining clauses
for the term and goal expansion hook predicates. Hook objects must be compiled
and loaded prior to being used to expand a source file.</p>
<p>To compile a source file using a hook object, we can use the
<a class="reference internal" href="programming.html#flag-hook"><span class="std std-ref">hook</span></a> compiler flag in the second argument of the
<a class="reference internal" href="../refman/predicates/logtalk_compile_2.html#predicates-logtalk-compile-2"><span class="std std-ref">logtalk_compile/2</span></a> and <a class="reference internal" href="../refman/predicates/logtalk_load_2.html#predicates-logtalk-load-2"><span class="std std-ref">logtalk_load/2</span></a>
built-in predicates. For example:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- logtalk_load(source_file, [hook(hook_object)]).
...
</pre></div>
</div>
<p>In alternative, we can use a <a class="reference internal" href="../refman/directives/set_logtalk_flag_2.html#directives-set-logtalk-flag-2"><span class="std std-ref">set_logtalk_flag/2</span></a>
directive in the source file itself. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">set_logtalk_flag</span>(hook, hook_object).
</pre></div>
</div>
<p>To use multiple hook objects in the same source file, simply write each
directive before the block of code that it should handle. For example:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">object</span>(h1,
    <span class="k">implements</span>(expanding)).

    <span class="k">term_expansion</span>((<span class="o">:-</span> public(a<span class="o">/</span><span class="m">0</span>)), (<span class="o">:-</span> public(b<span class="o">/</span><span class="m">0</span>))).
    <span class="k">term_expansion</span>(a, b).

<span class="p">:- </span><span class="k">end_object</span>.
</pre></div>
</div>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">object</span>(h2,
    <span class="k">implements</span>(expanding)).

    <span class="k">term_expansion</span>((<span class="o">:-</span> public(a<span class="o">/</span><span class="m">0</span>)), (<span class="o">:-</span> public(c<span class="o">/</span><span class="m">0</span>))).
    <span class="k">term_expansion</span>(a, c).

<span class="p">:- </span><span class="k">end_object</span>.
</pre></div>
</div>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">set_logtalk_flag</span>(hook, h1).

<span class="p">:- </span><span class="k">object</span>(s1).

<span class="p">    :- </span><span class="k">public</span>(a<span class="o">/</span><span class="m">0</span>).
    a.

<span class="p">:- </span><span class="k">end_object</span>.


<span class="p">:- </span><span class="k">set_logtalk_flag</span>(hook, h2).

<span class="p">:- </span><span class="k">object</span>(s2).

<span class="p">    :- </span><span class="k">public</span>(a<span class="o">/</span><span class="m">0</span>).
    a.

<span class="p">:- </span><span class="k">end_object</span>.
</pre></div>
</div>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- {h1, h2, s}.
...

| ?- s1::b.
yes

| ?- s2::c.
yes
</pre></div>
</div>
<p>It is also possible to define a default hook object by defining a global
value for the <code class="docutils literal notranslate"><span class="pre">hook</span></code> flag by calling the <a class="reference internal" href="../refman/predicates/set_logtalk_flag_2.html#predicates-set-logtalk-flag-2"><span class="std std-ref">set_logtalk_flag/2</span></a>
predicate. For example:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- set_logtalk_flag(hook, hook_object).

yes
</pre></div>
</div>
<p>Note that, due to the <code class="docutils literal notranslate"><span class="pre">set_logtalk_flag/2</span></code> directive being local to a source
file, using it to specify a hook object will override any defined default hook
object or any hook object specified as a <code class="docutils literal notranslate"><span class="pre">logtalk_compile/2</span></code> or <code class="docutils literal notranslate"><span class="pre">logtalk_load/2</span></code>
predicate compiler option for compiling or loading the source file.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Clauses for the <code class="docutils literal notranslate"><span class="pre">term_expansion/2</span></code> and <code class="docutils literal notranslate"><span class="pre">goal_expansion/2</span></code> predicates
defined within an object or a category are never used in the compilation
of the object or the category itself.</p>
</div>
</section>
<section id="virtual-source-file-terms-and-loading-context">
<span id="index-1"></span><span id="index-0"></span><h2>Virtual source file terms and loading context<a class="headerlink" href="#virtual-source-file-terms-and-loading-context" title="Link to this heading"></a></h2>
<p>When using a hook object to expand the terms of a source file, two
virtual file terms are generated: <code class="docutils literal notranslate"><span class="pre">begin_of_file</span></code> and <code class="docutils literal notranslate"><span class="pre">end_of_file</span></code>.
These terms allow the user to define term-expansions before and after
the actual source file terms.</p>
<p>Logtalk also provides a <a class="reference internal" href="../refman/predicates/logtalk_load_context_2.html#predicates-logtalk-load-context-2"><span class="std std-ref">logtalk_load_context/2</span></a>
built-in predicate that can be used to access the compilation/loading
context when performing expansions. The <a class="reference internal" href="objects.html#objects-logtalk"><span class="std std-ref">logtalk</span></a>
built-in object also provides a set of predicates that can be useful,
notably when adding Logtalk support for language extensions originally
developed for Prolog.</p>
<p>As an example of using the virtual terms and the <code class="docutils literal notranslate"><span class="pre">logtalk_load_context/2</span></code>
predicate, assume that you want to convert plain Prolog files to Logtalk by
wrapping the Prolog code in each file using an object (named after the file)
that implements a given protocol. This could be accomplished by defining
the following hook object:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">object</span>(wrapper(<span class="nv">_Protocol_</span>),
    <span class="k">implements</span>(expanding)).

    <span class="k">term_expansion</span>(begin_of_file, (<span class="o">:-</span> object(<span class="nv">Name</span>,implements(<span class="nv">_Protocol_</span>)))) <span class="o">:-</span>
        <span class="k">logtalk_load_context</span>(file, <span class="nv">File</span>),
        os<span class="o">::</span>decompose_file_name(<span class="nv">File</span>,<span class="nv">_</span> , <span class="nv">Name</span>, <span class="nv">_</span>).

    <span class="k">term_expansion</span>(end_of_file, (<span class="o">:-</span> end_object)).

<span class="p">:- </span><span class="k">end_object</span>.
</pre></div>
</div>
<p>Assuming, e.g., <code class="docutils literal notranslate"><span class="pre">my_car.pl</span></code> and <code class="docutils literal notranslate"><span class="pre">lease_car.pl</span></code> files  to be wrapped and
a <code class="docutils literal notranslate"><span class="pre">car_protocol</span></code> protocol, we could then load them using:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- logtalk_load(
         [&#39;my_car.pl&#39;, &#39;lease_car.pl&#39;],
         [hook(wrapper(car_protocol))]
     ).

yes
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>When a source file also contains plain Prolog directives and predicates,
these are term-expanded but not goal-expanded (with the exception of the
<code class="docutils literal notranslate"><span class="pre">initialization/1</span></code>, <code class="docutils literal notranslate"><span class="pre">if/1</span></code>, and <code class="docutils literal notranslate"><span class="pre">elif/1</span></code> directives, where the goal
argument is expanded to improve code portability across backends).</p>
</div>
</section>
<section id="default-compiler-expansion-workflow">
<h2>Default compiler expansion workflow<a class="headerlink" href="#default-compiler-expansion-workflow" title="Link to this heading"></a></h2>
<p>When <a class="reference internal" href="programming.html#programming-multi-pass-compiler"><span class="std std-ref">compiling a source file</span></a>,
the compiler will first try, by default,
the source file-specific hook object specified using a local
<code class="docutils literal notranslate"><span class="pre">set_logtalk_flag/2</span></code> directive, if defined. If that expansion fails,
it tries the hook object specified using the <code class="docutils literal notranslate"><span class="pre">hook/1</span></code> compiler option
in the <code class="docutils literal notranslate"><span class="pre">logtalk_compile/2</span></code> or <code class="docutils literal notranslate"><span class="pre">logtalk_load/2</span></code> goal that compiles
or loads the file, if defined. If that expansion fails, it tries the
default hook object, if defined. If that expansion also fails, the
compiler tries the Prolog dialect-specific expansion rules found
in the <a class="reference internal" href="../glossary.html#term-adapter-file"><span class="xref std std-term">adapter file</span></a> (which are used to support non-standard
Prolog features).</p>
</section>
<section id="user-defined-expansion-workflows">
<h2>User defined expansion workflows<a class="headerlink" href="#user-defined-expansion-workflows" title="Link to this heading"></a></h2>
<p>Sometimes we have multiple hook objects that we need to combine and use in
the compilation of a source file. Logtalk includes a <a class="reference internal" href="../libraries/hook_flows.html"><span class="doc">hook_flows</span></a>
library that supports two basic expansion workflows: a <a class="reference external" href="../../apis/hook_pipeline_1.html#hook-pipeline-1" title="(in Logtalk APIs v3.93.0)"><span class="xref std std-ref">pipeline</span></a>
of hook objects, where the expansion results from a hook object are fed to
the next hook object in the pipeline, and a <a class="reference external" href="../../apis/hook_set_1.html#hook-set-1" title="(in Logtalk APIs v3.93.0)"><span class="xref std std-ref">set</span></a> of
hook objects, where expansions are tried until one of them succeeds. These
workflows are implemented as parametric objects, allowing combining them to
implement more sophisticated expansion workflows. There is also a
<a class="reference internal" href="../libraries/hook_objects.html"><span class="doc">hook_objects</span></a> library that provides convenient hook
objects for defining custom expansion workflows. This library includes a
hook object that can be used to restore the default expansion workflow used
by the compiler.</p>
<p>For example, assuming that you want to apply the Prolog backend-specific
expansion rules defined in its adapter file, using the
<a class="reference external" href="../../apis/backend_adapter_hook_0.html#backend-adapter-hook-0" title="(in Logtalk APIs v3.93.0)"><span class="xref std std-ref">backend_adapter_hook</span></a> library object,
passing the resulting terms to your own expansion when compiling a source
file, we could use the goal:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- logtalk_load(
         source,
         [hook(hook_pipeline([backend_adapter_hook, my_expansion]))]
     ).
</pre></div>
</div>
<p>As a second example, we can prevent expansion of a source file using the library
object <a class="reference external" href="../../apis/identity_hook_0.html#identity-hook-0" title="(in Logtalk APIs v3.93.0)"><span class="xref std std-ref">identity_hook</span></a> by adding as the first term in a
source file the directive:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">set_logtalk_flag</span>(hook, identity_hook).
</pre></div>
</div>
<p>The file will be compiled as-is as any hook object (specified as a compiler
option or as a default hook object) and any backend adapter expansion rules
are overridden by the directive.</p>
</section>
<section id="using-prolog-defined-expansions">
<h2>Using Prolog defined expansions<a class="headerlink" href="#using-prolog-defined-expansions" title="Link to this heading"></a></h2>
<p>In order to use clauses for the <code class="docutils literal notranslate"><span class="pre">term_expansion/2</span></code> and <code class="docutils literal notranslate"><span class="pre">goal_expansion/2</span></code>
predicates defined in plain Prolog, simply specify the pseudo-object <code class="docutils literal notranslate"><span class="pre">user</span></code>
as the hook object when compiling source files. When using
<a class="reference internal" href="../glossary.html#term-backend-Prolog-compiler"><span class="xref std std-term">backend Prolog compilers</span></a> that support a
module system, it can also be specified a module containing clauses for the
expanding predicates as long as the module name doesn’t coincide with an
object name. When defining a custom workflow, the library object
<a class="reference external" href="../../apis/prolog_module_hook_1.html#prolog-module-hook-1" title="(in Logtalk APIs v3.93.0)"><span class="xref std std-ref">prolog_module_hook/1</span></a> can be used as a
workflow step. For example, assuming a module <code class="docutils literal notranslate"><span class="pre">functions</span></code> defining expansion
rules that we want to use:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- logtalk_load(
         source,
         [hook(hook_set([prolog_module_hook(functions), my_expansion]))]
     ).
</pre></div>
</div>
<p>But note that Prolog module libraries may provide definitions of the expansion
predicates that are not compatible with the Logtalk compiler. In particular,
when setting the hook object to <code class="docutils literal notranslate"><span class="pre">user</span></code>, be aware of any Prolog library that
is loaded, possibly by default or implicitly by the Prolog system, that may be
contributing definitions of the expansion predicates. It is usually safer to
define a specific hook object for combining multiple expansions in a fully
controlled way.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The <code class="docutils literal notranslate"><span class="pre">user</span></code> object declares <code class="docutils literal notranslate"><span class="pre">term_expansion/2</span></code> and <code class="docutils literal notranslate"><span class="pre">goal_expansion/2</span></code>
as multifile and dynamic predicates. This helps in avoiding predicate
existence errors when compiling source files with the <code class="docutils literal notranslate"><span class="pre">hook</span></code> flag set
to <code class="docutils literal notranslate"><span class="pre">user</span></code> as these predicates are only natively declared by some of the
supported backend Prolog compilers.</p>
</div>
</section>
<section id="debugging-expansions">
<h2>Debugging expansions<a class="headerlink" href="#debugging-expansions" title="Link to this heading"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">term_expansion/2</span></code> and <code class="docutils literal notranslate"><span class="pre">goal_expansion/2</span></code> predicates can be
<a class="reference internal" href="debugging.html#debugging-debugging"><span class="std std-ref">debugged</span></a> like any other object predicates. Note
that expansions can often be manually tested by sending
<a class="reference internal" href="../refman/methods/expand_term_2.html#methods-expand-term-2"><span class="std std-ref">expand_term/2</span></a> and <a class="reference internal" href="../refman/methods/expand_goal_2.html#methods-expand-goal-2"><span class="std std-ref">expand_goal/2</span></a>
messages to a hook object with the term or goal whose expansion you want to
check as argument. An alternative to the debugging tools is to use a
<a class="reference internal" href="../glossary.html#term-monitor"><span class="xref std std-term">monitor</span></a> for the runtime messages that call the predicates. For example,
assume a <code class="docutils literal notranslate"><span class="pre">expansions_debug.lgt</span></code> file with the contents:</p>
<div class="highlight-logtalk notranslate"><div class="highlight"><pre><span></span><span class="p">:- </span><span class="k">initialization</span>(
    <span class="k">define_events</span>(after, edcg, <span class="nv">_</span>, <span class="nv">_</span>, expansions_debug)
).


<span class="p">:- </span><span class="k">object</span>(expansions_debug,
    <span class="k">implements</span>(monitoring)).

    <span class="k">after</span>(edcg, <span class="k">term_expansion</span>(<span class="nv">T</span>,<span class="nv">E</span>), <span class="nv">_</span>) <span class="o">:-</span>
        <span class="k">writeq</span>(<span class="k">term_expansion</span>(<span class="nv">T</span>,<span class="nv">E</span>)), <span class="k">nl</span>.

<span class="p">:- </span><span class="k">end_object</span>.
</pre></div>
</div>
<p>We can use this monitor to help debug the expansion rules of the
<a class="reference internal" href="../libraries/edcg.html"><span class="doc">edcg</span></a> library when applied to the <code class="docutils literal notranslate"><span class="pre">edcgs</span></code> example using
the queries:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- {expansions_debug}.
...

| ?- set_logtalk_flag(events, allow).
yes

| ?- {edcgs(loader)}.
...
term_expansion(begin_of_file,begin_of_file)
term_expansion((:-object(gemini)),[(:-object(gemini)),(:-op(1200,xfx,--&gt;&gt;))])
term_expansion(acc_info(castor,A,B,C,true),[])
term_expansion(pass_info(pollux),[])
term_expansion(pred_info(p,1,[castor,pollux]),[])
term_expansion(pred_info(q,1,[castor,pollux]),[])
term_expansion(pred_info(r,1,[castor,pollux]),[])
term_expansion((p(A)--&gt;&gt;B is A+1,q(B),r(B)),(p(A,C,D,E):-B is A+1,q(B,C,F,E),r(B,F,D,E)))
term_expansion((q(A)--&gt;&gt;[]),(q(A,B,B,C):-true))
term_expansion((r(A)--&gt;&gt;[]),(r(A,B,B,C):-true))
term_expansion(end_of_file,end_of_file)
...
</pre></div>
</div>
<p>This solution does not require compiling the <code class="docutils literal notranslate"><span class="pre">edcg</span></code> hook object in debug
mode or access to its source code (e.g., to modify its expansion rules to
emit debug messages). We could also simply use the <code class="docutils literal notranslate"><span class="pre">user</span></code> pseudo-object
as the monitor object:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- assertz((
         after(_, term_expansion(T,E), _) :-
            writeq(term_expansion(T,E)), nl
     )).
yes

| ?- define_events(after, edcg, _, Sender, user).
yes
</pre></div>
</div>
<p>Another alternative is to use a pipeline of hook objects with the library
<code class="docutils literal notranslate"><span class="pre">hook_pipeline/1</span></code> and <code class="docutils literal notranslate"><span class="pre">write_to_stream_hook</span></code> objects to write the
expansion results to a file. For example, using the <code class="docutils literal notranslate"><span class="pre">unique.lgt</span></code> test
file from the <code class="docutils literal notranslate"><span class="pre">edcgs</span></code> library directory:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>| ?- {hook_flows(loader), hook_objects(loader)}.
...

| ?- open(&#39;unique_expanded.lgt&#39;, write, Stream),
     logtalk_compile(
         unique,
         [hook(hook_pipeline([edcg,write_to_stream_hook(Stream,[quoted(true)])]))]
     ),
     close(Stream).
...
</pre></div>
</div>
<p>The generated <code class="docutils literal notranslate"><span class="pre">unique_expanded.lgt</span></code> file will contain the clauses resulting
from the expansion of the EDCG rules found in the <code class="docutils literal notranslate"><span class="pre">unique.lgt</span></code> file by the
<code class="docutils literal notranslate"><span class="pre">edcg</span></code> hook object expansion.</p>
</section>
</section>


           </div>
          </div>
          <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
        <a href="printing.html" class="btn btn-neutral float-left" title="Printing messages and asking questions" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
        <a href="documenting.html" class="btn btn-neutral float-right" title="Documenting" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
    </div>

  <hr/>

  <div role="contentinfo">
    <p>&#169; Copyright 1998-2025, Paulo Moura.</p>
  </div>

  Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
    <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
    provided by <a href="https://readthedocs.org">Read the Docs</a>.
   

</footer>
        </div>
      </div>
    </section>
  </div>
  <script>
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script> 

</body>
</html>